package com.kk.xhr.admin.config.exception;

import com.kk.xhr.common.ErrorCodeEnum;
import com.kk.xhr.common.exception.BusinessException;
import com.kk.xhr.web.vo.ApiResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.context.request.async.AsyncRequestTimeoutException;

import javax.servlet.http.HttpServletRequest;
import java.util.Locale;
import java.util.concurrent.RejectedExecutionException;

/**
 * 异常处理类
 *
 * @author luokexiong
 * @version 1.0 2021/2/14
 * @since 1.0.0
 */
@Slf4j
@RestControllerAdvice
public class MyExceptionHandler {
    @Autowired
    private MessageSource messageSource;

    /**
     * NPE
     *
     * @param e NPE异常
     * @return json提示
     */
    @ExceptionHandler(NullPointerException.class)
    @ResponseBody
    public ResponseEntity<ApiResult<?>> npeException(NullPointerException e, Locale locale) {
        log.warn("NPE ", e);
        // ApiResult<?> result = ApiResult.failed(ErrorCodeEnum.UNKNOWN_ERROR, messageSource, locale);
        ApiResult<?> result = ApiResult.failed(ErrorCodeEnum.UNKNOWN_ERROR);
        return new ResponseEntity<>(result, HttpStatus.INTERNAL_SERVER_ERROR);
    }

    /**
     * http方法不对
     *
     * @param e http请求异常
     * @return json提示
     */
    @ResponseStatus(HttpStatus.METHOD_NOT_ALLOWED)
    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    public ApiResult<?> bindException(HttpRequestMethodNotSupportedException e, Locale locale) {
        log.debug("Http method not allowed.");
        // return ApiResult.failed(ErrorCodeEnum.METHOD_NOT_ALLOWED, messageSource, locale);
        return ApiResult.failed(ErrorCodeEnum.METHOD_NOT_ALLOWED);
    }

    /**
     * 业务异常
     *
     * @param e      business exception
     * @param locale 本地化
     * @return json提示
     */
    @ExceptionHandler(BusinessException.class)
    public ApiResult<?> businessException(BusinessException e, Locale locale) {
        // return ApiResult.failed(e.getErrorCode(), messageSource, locale, e.getArgs());
        return ApiResult.failed(e.getErrorCode());
    }

    /**
     * 未知异常
     *
     * @param e 未知异常
     * @return json提示
     */
    @ExceptionHandler(Exception.class)
    @ResponseBody
    public ResponseEntity<ApiResult<?>> unknownException(Exception e, Locale locale) {
        log.warn("Exception ", e);
        // ApiResult<?> result = ApiResult.failed(ErrorCodeEnum.UNKNOWN_ERROR, messageSource, locale);
        ApiResult<?> result = ApiResult.failed(ErrorCodeEnum.UNKNOWN_ERROR);
        return new ResponseEntity<>(result, HttpStatus.INTERNAL_SERVER_ERROR);
    }

    /**
     * 异步请求超时异常
     *
     * @param e       异常
     * @param request 请求
     * @param locale  locale
     * @return timeout提示
     */
    @ExceptionHandler(AsyncRequestTimeoutException.class)
    @ResponseBody
    public ResponseEntity<ApiResult<?>> asyncRequestTimeoutException(AsyncRequestTimeoutException e, HttpServletRequest request, Locale locale) {
        if (log.isInfoEnabled()) {
            log.info("Async request timeout: {}", request.getRequestURI());
        }
        // return new ResponseEntity<>(ApiResult.failed(ErrorCodeEnum.TIMEOUT, messageSource, locale),
        //     HttpStatus.REQUEST_TIMEOUT);
        return new ResponseEntity<>(ApiResult.failed(ErrorCodeEnum.TIMEOUT),
            HttpStatus.REQUEST_TIMEOUT);
    }

    /**
     * 线程任务被拒绝异常
     *
     * @param e RejectedExecutionException
     * @return json提示
     */
    @ExceptionHandler(RejectedExecutionException.class)
    @ResponseBody
    public ApiResult<?> rejectedExecutionException(RejectedExecutionException e, Locale locale) {
        log.warn("Thread submission has been rejected, {}", e.getMessage());
        // return ApiResult.failed(ErrorCodeEnum.UNKNOWN_ERROR, messageSource, locale);
        return ApiResult.failed(ErrorCodeEnum.UNKNOWN_ERROR);
    }
}
